bitkeeper revision 1.541.1.1 (3fa14b5aVZfwzFArgab1vhsTUV0TOA)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 30 Oct 2003 17:33:14 +0000 (17:33 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 30 Oct 2003 17:33:14 +0000 (17:33 +0000)
time.c, hypervisor.h, kernel.c, head.S:
  Fix minios to work with revised Xen 1.2 interface.

extras/mini-os/h/hypervisor.h
extras/mini-os/head.S
extras/mini-os/kernel.c
extras/mini-os/time.c

index 23c39134f38ea8fce7dc0627d547c44143ea6076..4c4d752615d919650a406629eef5f16f7e0920b1 100644 (file)
@@ -255,4 +255,16 @@ static inline long HYPERVISOR_kbd_op(unsigned char op, unsigned char val)
     return ret;
 }
 
+static inline int HYPERVISOR_update_va_mapping(
+    unsigned long page_nr, unsigned long new_val, unsigned long flags)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret) : "0" (__HYPERVISOR_update_va_mapping), 
+        "b" (page_nr), "c" (new_val), "d" (flags) );
+
+    return ret;
+}
+
 #endif /* __HYPERVISOR_H__ */
index d5cb19f574c36efad5aa29b3d64badda1f42ee79..4a2ccbbe1eea78cc2ebfb3743371bbc3a81d8f3c 100644 (file)
@@ -4,9 +4,8 @@
 #define MOD_START    4
 #define MOD_LEN      8
 
-#define ENTRY(X) .globl X ; X :
-
-.globl _start                
+.globl _start, shared_info
+                        
 _start:
         cld
         
@@ -43,3 +42,7 @@ stack_start:
        .long stack+8192, __KERNEL_DS
 
 
+        /* Unpleasant -- we actually use this PTE to map shared_info :-) */
+        .org 0x1000
+shared_info:
+        .org 0x2000
index 12d36f1347a9f6008b24ea295b9577b438354b02..0ead3f18d3d8f886ed2287e33539baae1628ce00 100644 (file)
@@ -61,6 +61,19 @@ static void exit_handler(int ev, struct pt_regs *regs);
 static void debug_handler(int ev, struct pt_regs *regs);
 
 
+static shared_info_t *map_shared_info(unsigned long pa)
+{
+    extern char shared_info[PAGE_SIZE];
+    if ( HYPERVISOR_update_va_mapping((unsigned long)shared_info >> PAGE_SHIFT,
+                                      pa | 3, UVMF_INVLPG) )
+    {
+        printk("Failed to map shared_info!!\n");
+        *(int*)0=0;
+    }
+    return (shared_info_t *)shared_info;
+}
+
+
 /*
  * INITIAL C ENTRY POINT.
  */
@@ -72,25 +85,23 @@ void start_kernel(start_info_t *si)
     memcpy(&start_info, si, sizeof(*si));
 
     /* Grab the shared_info pointer and put it in a safe place. */
-    HYPERVISOR_shared_info = start_info.shared_info;
+    HYPERVISOR_shared_info = map_shared_info(start_info.shared_info);
 
     /* Set up event and failsafe callback addresses. */
     HYPERVISOR_set_callbacks(
         __KERNEL_CS, (unsigned long)hypervisor_callback,
         __KERNEL_CS, (unsigned long)failsafe_callback);
 
-
     trap_init();
 
-
     /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
     __sti();
     
     /* print out some useful information  */
     printk("Xeno Minimal OS!\n");
     printk("start_info:   %p\n",  si);
-    printk("  nr_pages:   %lu",   si->nr_pages);
-    printk("  shared_inf: %p\n",  si->shared_info);
+    printk("  nr_pages:   %lu",     si->nr_pages);
+    printk("  shared_inf: %08lx\n", si->shared_info);
     printk("  pt_base:    %p",    (void *)si->pt_base); 
     printk("  mod_start:  0x%lx\n", si->mod_start);
     printk("  mod_len:    %lu\n", si->mod_len); 
@@ -142,7 +153,7 @@ void start_kernel(start_info_t *si)
 void do_exit(void)
 {
     printk("do_exit called!\n");
-    for ( ;; ) ;
+    for ( ;; ) HYPERVISOR_exit();
 }
 static void exit_handler(int ev, struct pt_regs *regs) {
     do_exit();
index 8e7de4e20d250e5075985ed8c928c06a868b75d7..23b31794ba90f99af5f95eda10e8c68536c8cca8 100644 (file)
  *************************************************************************/
 
 static unsigned int rdtsc_bitshift;
-static u32      st_scale_f;
-static u32      st_scale_i;
-static u32      shadow_st_pcc;
-static s_time_t shadow_st;
-static u32      shadow_wc_version=0;
-static long     shadow_tv_sec;
-static long     shadow_tv_usec;
-static s_time_t shadow_wc_timestamp;
-
-/*
- * System time.
- * We need to read the values from the shared info page "atomically" 
- * and use the cycle counter value as the "version" number. Clashes
- * should be very rare.
- */
-inline s_time_t get_s_time(void)
+static u32 st_scale_f; /* convert ticks -> usecs */
+static u32 st_scale_i; /* convert ticks -> usecs */
+
+/* These are peridically updated in shared_info, and then copied here. */
+static u32 shadow_tsc_stamp;
+static s64 shadow_system_time;
+static u32 shadow_time_version;
+static struct timeval shadow_tv;
+
+#ifndef rmb
+#define rmb()  __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#endif
+
+#define HANDLE_USEC_OVERFLOW(_tv)          \
+    do {                                   \
+        while ( (_tv).tv_usec >= 1000000 ) \
+        {                                  \
+            (_tv).tv_usec -= 1000000;      \
+            (_tv).tv_sec++;                \
+        }                                  \
+    } while ( 0 )
+
+static void get_time_values_from_xen(void)
 {
-    s32 delta_tsc;
-    u32 low;
-    u64 delta, tsc;
-    u32        version;
-    u64 cpu_freq, scale;
-
-    /* check if our values are still up-to-date */
-    while ( (version = HYPERVISOR_shared_info->wc_version) != 
-            shadow_wc_version )
-    {
-        barrier();
-
-        shadow_wc_version   = version;
-        shadow_tv_sec       = HYPERVISOR_shared_info->tv_sec;
-        shadow_tv_usec      = HYPERVISOR_shared_info->tv_usec;
-        shadow_wc_timestamp = HYPERVISOR_shared_info->wc_timestamp;
-        shadow_st_pcc       = HYPERVISOR_shared_info->st_timestamp;
-        shadow_st           = HYPERVISOR_shared_info->system_time;
-
-        rdtsc_bitshift      = HYPERVISOR_shared_info->rdtsc_bitshift;
-        cpu_freq            = HYPERVISOR_shared_info->cpu_freq;
-
-        /* XXX cpu_freq as u32 limits it to 4.29 GHz. Get a better do_div! */
-        scale = 1000000000LL << (32 + rdtsc_bitshift);
-        scale /= cpu_freq;
-        st_scale_f = scale & 0xffffffff;
-        st_scale_i = scale >> 32;
-
-        barrier();
-       }
+    do {
+        shadow_time_version = HYPERVISOR_shared_info->time_version2;
+        rmb();
+        shadow_tv.tv_sec    = HYPERVISOR_shared_info->wc_sec;
+        shadow_tv.tv_usec   = HYPERVISOR_shared_info->wc_usec;
+        shadow_tsc_stamp    = HYPERVISOR_shared_info->tsc_timestamp;
+        shadow_system_time  = HYPERVISOR_shared_info->system_time;
+        rmb();
+    }
+    while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 );
+}
+
+
+#define TIME_VALUES_UP_TO_DATE \
+    (shadow_time_version == HYPERVISOR_shared_info->time_version2)
+
+
+static inline unsigned long get_time_delta_usecs(void)
+{
+    s32      delta_tsc;
+    u32      low;
+    u64      delta, tsc;
 
     rdtscll(tsc);
     low = (u32)(tsc >> rdtsc_bitshift);
-    delta_tsc = (s32)(low - shadow_st_pcc);
+    delta_tsc = (s32)(low - shadow_tsc_stamp);
     if ( unlikely(delta_tsc < 0) ) delta_tsc = 0;
     delta = ((u64)delta_tsc * st_scale_f);
     delta >>= 32;
     delta += ((u64)delta_tsc * st_scale_i);
 
-    return shadow_st + delta;
+    return (unsigned long)delta;
 }
 
 
-/*
- * Wallclock time.
- * Based on what the hypervisor tells us, extrapolated using system time.
- * Again need to read a number of values from the shared page "atomically".
- * this time using a version number.
- */
 void gettimeofday(struct timeval *tv)
 {
-    long          usec, sec;
-    u64           now;
-
-    now   = get_s_time();
-    usec  = ((unsigned long)(now-shadow_wc_timestamp))/1000;
-    sec   = shadow_tv_sec;
-    usec += shadow_tv_usec;
-
-    while ( usec >= 1000000 ) 
-    {
-        usec -= 1000000;
-        sec++;
+    struct timeval _tv;
+
+    do {
+        get_time_values_from_xen();
+        _tv.tv_usec = get_time_delta_usecs();
+        _tv.tv_sec   = shadow_tv.tv_sec;
+        _tv.tv_usec += shadow_tv.tv_usec;
     }
+    while ( unlikely(!TIME_VALUES_UP_TO_DATE) );
 
-    tv->tv_sec = sec;
-    tv->tv_usec = usec;
+    HANDLE_USEC_OVERFLOW(_tv);
+    *tv = _tv;
 }
 
 
 static void timer_handler(int ev, struct pt_regs *regs)
 {
     static int i;
-    s_time_t now;
+    struct timeval tv;
 
     i++;
     if (i >= 1000) {
-        now = get_s_time();
-        printf("T(%lld)\n", now);
+        gettimeofday(&tv);
+        printf("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
         i = 0;
     }
 }
@@ -150,12 +139,21 @@ static void timer_handler(int ev, struct pt_regs *regs)
 
 void init_time(void)
 {
-    u64         __cpu_khz;
+    u64         __cpu_khz, cpu_freq, scale;
     unsigned long cpu_khz;
 
     __cpu_khz = HYPERVISOR_shared_info->cpu_freq;
     cpu_khz = (u32) (__cpu_khz/1000);
 
+    rdtsc_bitshift = HYPERVISOR_shared_info->rdtsc_bitshift;
+    cpu_freq       = HYPERVISOR_shared_info->cpu_freq;
+
+    scale = 1000000LL << (32 + rdtsc_bitshift);
+    scale /= cpu_freq;
+
+    st_scale_f = scale & 0xffffffff;
+    st_scale_i = scale >> 32;
+
     printk("Xen reported: %lu.%03lu MHz processor.\n", 
            cpu_khz / 1000, cpu_khz % 1000);